package automatagen;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Properties;

public class Automata {
	
	private String Service;
	private ServiceType type;
    private ArrayList<Tripla> triplas = new ArrayList<Tripla>();
    private ArrayList<Tripla> triplasPos = new ArrayList<Tripla>();
	private ArrayList<Tupla> preTuplas = new ArrayList<Tupla>();
    private ArrayList<Tupla> posTuplas = new ArrayList<Tupla>();
	private AutomataGen autGen;
	
	public ArrayList<Tripla> getTriplasPos() {
		return triplasPos;
	}
	
	public void setAutomataGen(AutomataGen autGen){
		this.autGen = autGen;
	}
	
	public AutomataGen getAutomataGen(){
		return this.autGen;
	}
	
	public String getService() {
		return Service;
	}

	public ServiceType getType() {
		return type;
	}
	
	public ArrayList<Tripla> getTripla() {
		return triplas;
	}

    public void addTriplas(ServiceType type, ArrayList<Tripla> triplas){
	if (type == ServiceType.POS){
	    this.triplasPos = triplas;
	}else {//if(type == ServiceType.PRE) {
	    this.triplas = triplas;
	}
    }

    public Automata(String Service,ServiceType type, ArrayList<Tripla> triplas) {
		this.Service = Service;
		this.type = type;
		if (type == ServiceType.POS){
		    this.triplasPos = triplas;
		}else {//if(type == ServiceType.PRE) {
		    this.triplas = triplas;
		}
		/*if (triplas == null){
			this.triplas = new ArrayList<Tripla>();
			}*/
		//System.out.println("FEZ!");
	}
    public void generateStates(){
    	this.preTuplas = generatePreStates();
    	this.posTuplas = generatePosStates();
    }
    
    public ArrayList<Tupla> getPreTuplas() {
		return preTuplas;
	}

	public ArrayList<Tupla> getPosTuplas() {
		return posTuplas;
	}

	public ArrayList<Tupla> generatePosStates(){
		try{
			if (triplasPos.size() > 0){
				return generateStates(this.getTriplasPos(), 0);
			}else{
				return new ArrayList<Tupla>();
			}
		}catch (NullPointerException npe){
			System.err.println("Automata Gen Não especificado!");
			npe.printStackTrace();
			return new ArrayList<Tupla>();
		}
	}
    
	public ArrayList<Tupla> generatePreStates(){
		try{
			if (triplas.size() > 0){
				return generateStates(this.getTripla(), 0);
			}else{
				return new ArrayList<Tupla>();
			}
		}catch (NullPointerException npe){
			System.err.println("Automata Gen Não especificado!");
			npe.printStackTrace();
			return new ArrayList<Tupla>();
		}
	}
	
	private ArrayList<Tupla> generateStates(ArrayList<Tripla> preStates, int level) throws NullPointerException {
		ArrayList<Tupla> retorno = new ArrayList<Tupla>();
		ArrayList<Tupla> retBuffer = new ArrayList<Tupla>();
		//StringBuffer currentString;
		ArrayList<Tripla> currentTriplas;
		int c = 0;
		for (Tripla tripla : preStates) {
			retBuffer = new ArrayList<Tupla>();

			//////////////////////////////////////// GERANDO MAPEAMENTO DE ACESSOS (MASCARAS E TRATAMENTO DE DADOS)
			autGen.addAccessMethod(tripla.getFirst(), tripla.getAccessMethod(autGen));
			////////////////////////////////////////
			
			currentTriplas = tripla.getTriplas();
			if (currentTriplas.size() > 0){
				retBuffer.addAll(generateStates(currentTriplas,level+1));
			}
			//retorno.addAll(retBuffer);
			//System.out.println(c + " Add: " + tripla.getSecond() + " - " + level);
			retorno.addAll(0,retBuffer);
			retorno.add(0,new Tupla(tripla, new Integer(level)));
			//System.out.println(c + " Add_subs: " + retBuffer.toString());
			c++; //Rá...
		}
		//prop.setProperty(currentString.toString(), Integer.toString(level));
		//retorno.add(prop);v
		//System.out.println("Add: ".concat(retBuffer.size()>0?retBuffer.get(0).obj2.toString():"null"));
		//System.out.println("RETORNO: " + retorno.toString());
		return retorno;
	}
	
	private String spaces(int level){
		StringBuffer ret = new StringBuffer("");
		for (int i = 0; i < level; i++) {
			ret.append("\t");
		}
		return ret.toString();
	}
	
	public String getName(){
		if (this.getType()==ServiceType.NULL){
			return this.getService();
		}else{
			//return this.getService().concat("_").concat(this.getType().toString());
			return this.getService();
		}
	}
	public int getNextIndexOfSameLevel(ArrayList<Tupla> tuplas, int level, int currentIndex){
		for (int i = currentIndex+1;i<tuplas.size();i++){
			if ((Integer)tuplas.get(i).obj2 == level){
				return i;
			}
		}
		return -1;
	}
}
